﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Xml;

namespace IceFireDM
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load("wiki.htm");

            //doc.SelectNodes("/div/h2")
            var houses = ParseWiki(doc).ToArray();
            RemoveGarbageBio(houses);
            RetrieveArms(houses);
            ToDB(houses);
        }

        private static void ToDB(House[] houses)
        {
            using (SongEntities dc = new SongEntities())
            {
                foreach (var house in houses)
                {
                    var t = new Table_1();
                    t.ID = house.Id;
                    t.Name = house.Name;
                    t.Img = house.CoatOfArms.Binary;

                    dc.Table_1.AddObject(t);
                }

                dc.SaveChanges();
            }
        }

        private static void RetrieveArms(House[] houses)
        {
            using (WebClient wc = new WebClient())
            {
                foreach (var house in houses)
                {
                    var url = "http:" + house.CoatOfArms.Url;
                    house.CoatOfArms.Binary = wc.DownloadData(url);
                }
            }
        }

        private static void RemoveGarbageBio(House[] houses)
        {
            foreach (var house in houses)
            {
                foreach (var notable in house.Notables)
                {
                    if (notable.Biography.Last().Contains("portrayed by"))
                        notable.Biography.Remove(notable.Biography.Last());
                }
            }
        }

        private static IEnumerable<House> ParseWiki(XmlDocument doc)
        {
            int hid = 1, nid = 1;
            var it = doc.DocumentElement.ChildNodes.GetEnumerator();

            House currentHouse = null;
            Notable currentNotable = null;
            bool house = false;

            while (it.MoveNext())
            {
                var e = it.Current as XmlNode;

                if (e.Name == "h2")
                {
                    if (currentHouse != null)
                        yield return currentHouse;

                    currentHouse = new House();
                    currentHouse.Id = hid++;
                    currentHouse.Name = e.SelectSingleNode("span[2]").InnerText.HtmlTrim();
                    house = true;
                }
                else if (e.Name == "div")
                {
                    if (currentHouse != null)
                        currentHouse.CoatOfArms.Url = e.SelectSingleNode("div/a/img").Attributes["src"].Value;
                }
                else if (e.Name == "p")
                {
                    if (house)
                    {
                        currentHouse.Biography.Add(e.InnerText.HtmlTrim());
                    }
                    else
                    {
                        currentNotable.Biography.Add(e.InnerText.HtmlTrim());
                    }
                }
                else if (e.Name == "h3")
                {
                    currentNotable = new Notable();
                    currentNotable.Id = nid++;
                    currentNotable.Name = e.SelectSingleNode("span[2]").InnerText.HtmlTrim();

                    if (currentHouse != null)
                        currentHouse.Notables.Add(currentNotable);

                    house = false;
                }

                //yield return new House();
            }

            if (currentHouse != null)
                yield return currentHouse;
        }


        class House
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public List<string> Biography { get; set; }
            public HouseImage CoatOfArms { get; set; }
            public List<Notable> Notables { get; set; }

            public House()
            {
                Biography = new List<string>();
                Notables = new List<Notable>();
                CoatOfArms = new HouseImage();
            }
        }

        class HouseImage
        {
            public string Url { get; set; }
            public byte[] Binary { get; set; }
        }

        class Notable
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public List<string> Biography { get; set; }

            public Notable()
            {
                Biography = new List<string>();
            }
        }
    }

    public static class StringExtension
    {
        public static string HtmlTrim(this string source)
        {
            if (String.IsNullOrEmpty(source))
                return String.Empty;

            var q = source.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim());
            var s = String.Join(" ", q);
            return s;
        }
    }
}
